# Copyright (c) 2021 Red Hat, Inc. All rights reserved. This copyrighted
# material is made available to anyone wishing to use, modify, copy, or
# redistribute it subject to the terms and conditions of the GNU General Public
# License v.2 or later.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""The "domain" command."""
import re

from kpet import cmd_misc
from kpet import data
from kpet import misc


def build(cmds_parser, common_parser):
    """Build the argument parser for the domain command."""
    _, action_subparser = cmd_misc.build(
        cmds_parser,
        common_parser,
        "domain",
        help='Host domains',
    )
    list_parser = action_subparser.add_parser(
        "tree",
        help='Output the (filtered) tree of domains.',
        parents=[common_parser],
    )
    list_parser.add_argument('regexes', metavar='REGEX', nargs='*',
                             default=[],
                             help='Regular expression fully matching '
                                  'slash-separated paths of domains to '
                                  'output. Matching domains are output with '
                                  'their sub-domains.')


def print_domains(prefix, domains, regexes):
    """
    Print a list of domains.

    Print a list of domains, along with subdomains, optionally filtered by a
    list of path regexes.

    Args:
        prefix:     A string to print in front of each line.
        domains:    The list of domains to filter and print.
        regexes:    A list of compiled regular expressions matching paths of
                    domains to print, along with their subdomains.
    """
    # For each domain in the dictionary
    for i, domain in enumerate(domains.values()):
        # Finish the line with the domain description, if any
        suffix = (" " + repr(domain.description)) \
            if domain.description is not None else ""
        subregexes = regexes
        # If we're not on top level anymore and aren't filtering
        if regexes is None:
            # If it's not the last domain in the dictionary
            if i + 1 < len(domains):
                domain_prefix = prefix + "|-- "
                domain_subprefix = prefix + "|   "
            else:
                domain_prefix = prefix + "`-- "
                domain_subprefix = prefix + "    "
            # Print the domain name
            print(domain_prefix + domain.name + suffix)
        else:
            domain_prefix = prefix
            domain_subprefix = prefix
            # If the domain matches a regex
            if any(r.fullmatch(domain.path) for r in regexes):
                # Print the domain path
                print(domain_prefix + domain.path + suffix)
                # Don't filter subdomains
                subregexes = None
        # Print subdomains
        print_domains(domain_subprefix,
                      domain.domains or {}, subregexes)


def main(args):
    """Execute the `domain` command."""
    if not data.Base.is_dir_valid(args.db):
        misc.raise_invalid_database(args.db)
    database = data.Base(args.db)
    if args.action == 'tree':
        if database.domains is None:
            raise Exception("Database has no domains defined")
        print_domains("", database.domains or {},
                      [re.compile(r) for r in args.regexes] or
                      [re.compile(".*")])
    else:
        misc.raise_action_not_found(args.action, args.command)
